#ifndef H_KOGI_ITEM_H
#define H_KOGI_ITEM_H

#include <stddef.h>
#include <stdint.h>

#ifndef NDEBUG
#define KOGI_ENABLE_ITEM_TYPE_SAFETY
#endif

enum kogi_item_type {
    KOGI_ITEM_CHAR,
    KOGI_ITEM_CSTRING,
    KOGI_ITEM_DOUBLE,
    KOGI_ITEM_FLOAT,
    KOGI_ITEM_INT,
    KOGI_ITEM_INT8,
    KOGI_ITEM_INT16,
    KOGI_ITEM_INT32,
    KOGI_ITEM_INT64,
    KOGI_ITEM_LONG,
    KOGI_ITEM_LLONG,
    KOGI_ITEM_SHORT,
    KOGI_ITEM_UCHAR,
    KOGI_ITEM_UINT,
    KOGI_ITEM_UINT8,
    KOGI_ITEM_UINT16,
    KOGI_ITEM_UINT32,
    KOGI_ITEM_UINT64,
    KOGI_ITEM_ULONG,
    KOGI_ITEM_ULLONG,
    KOGI_ITEM_USHORT,
    KOGI_ITEM_PTR,
    KOGI_ITEM_CONSTPTR,
    KOGI_ITEM_SIZET
};

struct kogi_item {
    union {
        char c;
        char const* cstr;
        double d;
        float f;
        int i;
        int8_t i8;
        int16_t i16;
        int32_t i32;
        int64_t i64;
        long l;
        long long ll;
        short s;
        uint8_t u8;
        uint16_t u16;
        uint32_t u32;
        uint64_t u64;
        unsigned u;
        unsigned char uc;
        unsigned long ul;
        unsigned long long ull;
        unsigned short us;
        void* ptr;
        void const* cptr;
        size_t szt;
    } data;
#ifdef KOGI_ENABLE_ITEM_TYPE_SAFETY
    enum kogi_item_type type;
#endif
};

// data -> kogi
static inline struct kogi_item      kogi_from_char(char);
static inline struct kogi_item      kogi_from_cstr(char const*);
static inline struct kogi_item      kogi_from_double(double);
static inline struct kogi_item      kogi_from_float(float);
static inline struct kogi_item      kogi_from_int(int);
static inline struct kogi_item      kogi_from_int8(int8_t);
static inline struct kogi_item      kogi_from_int16(int16_t);
static inline struct kogi_item      kogi_from_ullong(unsigned long long);

// kogi -> data
static inline char                  kogi_to_char(struct kogi_item);
static inline char const*           kogi_to_cstr(struct kogi_item);
static inline double                kogi_to_double(struct kogi_item);
static inline float                 kogi_to_float(struct kogi_item);
static inline int                   kogi_to_int(struct kogi_item);
static inline int8_t                kogi_to_int8_t(struct kogi_item);
static inline int16_t               kogi_to_int16_t(struct kogi_item);
static inline unsigned long long    kogi_to_ullong(struct kogi_item);

#include "internal/item.inl"

#endif

